package com.example.mgsnew.config;

import com.example.mgsnew.Handler.NotificationHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class NettyServer_2 {

    @Value("${netty.port:8284}")
    private int wsPort;

    @Value("${netty.boss.threads:1}")
    private int bossThreads;

    @Value("${netty.worker.threads:4}")
    private int workerThreads;

    @Value("${netty.max.frame.size:65536}")
    private int maxFrameSize;

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel serverChannel;
    private final ExecutorService startupExecutor = Executors.newSingleThreadExecutor();

    @PostConstruct
    public void start() {
        startupExecutor.submit(this::startWebSocketServer);
    }

    private void startWebSocketServer() {
        bossGroup = new NioEventLoopGroup(bossThreads);
        workerGroup = new NioEventLoopGroup(workerThreads);

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            // HTTP 协议处理（必须保留，用于 WebSocket 握手）
                            pipeline.addLast(new HttpServerCodec());
                            pipeline.addLast(new ChunkedWriteHandler());
                            pipeline.addLast(new HttpObjectAggregator(maxFrameSize)); // 64KB 聚合限制

                            // WebSocket 协议处理
                            pipeline.addLast(new WebSocketServerProtocolHandler(
                                    "/ws/notification", null, true, 65536));

                            // 自定义业务处理器
                            pipeline.addLast(new NotificationHandler());
                        }
                    });

            // 绑定端口并同步等待
            ChannelFuture future = bootstrap.bind(wsPort).sync();
            serverChannel = future.channel();

            log.info("Netty WebSocket 服务器已启动，端口: {}", wsPort);

            // 等待服务器关闭
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("Netty WebSocket 服务器启动被中断", e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            log.error("Netty WebSocket 服务器启动失败", e);
        }
    }

    @PreDestroy
    public void stop() {
        log.info("正在关闭 Netty WebSocket 服务器...");

        // 关闭服务器通道
        if (serverChannel != null) {
            serverChannel.close();
        }

        // 优雅关闭 EventLoopGroup
        if (bossGroup != null) {
            bossGroup.shutdownGracefully(500, 2000, TimeUnit.MILLISECONDS);
        }

        if (workerGroup != null) {
            workerGroup.shutdownGracefully(500, 2000, TimeUnit.MILLISECONDS);
        }

        // 关闭启动线程池
        if (startupExecutor != null) {
            startupExecutor.shutdown();
            try {
                if (!startupExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
                    startupExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                startupExecutor.shutdownNow();
            }
        }

        log.info("Netty WebSocket 服务器已关闭");
    }
}